package com.secret.chain.secretchain.solidity;

import org.fisco.bcos.sdk.abi.FunctionReturnDecoder;
import org.fisco.bcos.sdk.abi.TypeReference;
import org.fisco.bcos.sdk.abi.datatypes.Function;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.Utf8String;
import org.fisco.bcos.sdk.abi.datatypes.generated.Uint256;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple5;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.contract.Contract;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@SuppressWarnings("unchecked")
public class Answer extends Contract {
    public static final String[] BINARY_ARRAY = {"608060405234801561001057600080fd5b50610410806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063200d2ed2146100675780633c079c4d146100855780638a4d5a6714610168578063a2e62045146101eb578063b5b0914214610209578063efc81a8c14610227575b600080fd5b61006f610245565b6040518082815260200191505060405180910390f35b610166600480360360a081101561009b57600080fd5b8101908080359060200190929190803590602001906401000000008111156100c257600080fd5b8201836020820111156100d457600080fd5b803590602001918460018302840111640100000000831117156100f657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190803590602001909291908035906020019092919050505061024b565b005b610170610285565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101b0578082015181840152602081019050610195565b50505050905090810190601f1680156101dd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101f3610323565b6040518082815260200191505060405180910390f35b610211610329565b6040518082815260200191505060405180910390f35b61022f61032f565b6040518082815260200191505060405180910390f35b60045481565b846000819055508360019080519060200190610268929190610335565b508260028190555081600381905550806004819055505050505050565b60018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561031b5780601f106102f05761010080835404028352916020019161031b565b820191906000526020600020905b8154815290600101906020018083116102fe57829003601f168201915b505050505081565b60035481565b60005481565b60025481565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061037657805160ff19168380011785556103a4565b828001600101855582156103a4579182015b828111156103a3578251825591602001919060010190610388565b5b5090506103b191906103b5565b5090565b6103d791905b808211156103d35760008160009055506001016103bb565b5090565b9056fea2646970667358221220af60ae428b87af6d64c9eb831af2902408bdd6ea10c965d5042aeae8dbab9b4164736f6c634300060a0033"};

    public static final String BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", BINARY_ARRAY);

    public static final String[] SM_BINARY_ARRAY = {"608060405234801561001057600080fd5b50610410806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063200d2ed2146100675780633c079c4d146100855780638a4d5a6714610168578063a2e62045146101eb578063b5b0914214610209578063efc81a8c14610227575b600080fd5b61006f610245565b6040518082815260200191505060405180910390f35b610166600480360360a081101561009b57600080fd5b8101908080359060200190929190803590602001906401000000008111156100c257600080fd5b8201836020820111156100d457600080fd5b803590602001918460018302840111640100000000831117156100f657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929080359060200190929190803590602001909291908035906020019092919050505061024b565b005b610170610285565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101b0578082015181840152602081019050610195565b50505050905090810190601f1680156101dd5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101f3610323565b6040518082815260200191505060405180910390f35b610211610329565b6040518082815260200191505060405180910390f35b61022f61032f565b6040518082815260200191505060405180910390f35b60045481565b846000819055508360019080519060200190610268929190610335565b508260028190555081600381905550806004819055505050505050565b60018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561031b5780601f106102f05761010080835404028352916020019161031b565b820191906000526020600020905b8154815290600101906020018083116102fe57829003601f168201915b505050505081565b60035481565b60005481565b60025481565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061037657805160ff19168380011785556103a4565b828001600101855582156103a4579182015b828111156103a3578251825591602001919060010190610388565b5b5090506103b191906103b5565b5090565b6103d791905b808211156103d35760008160009055506001016103bb565b5090565b9056fea2646970667358221220af60ae428b87af6d64c9eb831af2902408bdd6ea10c965d5042aeae8dbab9b4164736f6c634300060a0033"};

    public static final String SM_BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);

    public static final String[] ABI_ARRAY = {"[{\"name\":\"content\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"indexed\":false,\"components\":null,\"typeAsString\":\"string\"}],\"methodSignatureAsString\":\"content()\"},{\"name\":\"create\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"create()\"},{\"name\":\"problemId\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"problemId()\"},{\"name\":\"set\",\"type\":\"function\",\"constant\":false,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"nonpayable\",\"inputs\":[{\"name\":\"_problemId\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"_content\",\"type\":\"string\",\"indexed\":false,\"components\":null,\"typeAsString\":\"string\"},{\"name\":\"_create\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"_update\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"},{\"name\":\"_status\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"outputs\":[],\"methodSignatureAsString\":\"set(uint256,string,uint256,uint256,uint256)\"},{\"name\":\"status\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"status()\"},{\"name\":\"update\",\"type\":\"function\",\"constant\":true,\"payable\":false,\"anonymous\":false,\"stateMutability\":\"view\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"components\":null,\"typeAsString\":\"uint256\"}],\"methodSignatureAsString\":\"update()\"}]"};

    public static final String ABI = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", ABI_ARRAY);

    public static final String FUNC_CONTENT = "content";

    public static final String FUNC_CREATE = "create";

    public static final String FUNC_PROBLEMID = "problemId";

    public static final String FUNC_SET = "set";

    public static final String FUNC_STATUS = "status";

    public static final String FUNC_UPDATE = "update";

    protected Answer(String contractAddress, Client client, CryptoKeyPair credential) {
        super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    }

    public static String getBinary(CryptoSuite cryptoSuite) {
        return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    }

    public String content() throws ContractException {
        final Function function = new Function(FUNC_CONTENT, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
        return executeCallWithSingleValueReturn(function, String.class);
    }

    public BigInteger create() throws ContractException {
        final Function function = new Function(FUNC_CREATE, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public BigInteger problemId() throws ContractException {
        final Function function = new Function(FUNC_PROBLEMID, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public TransactionReceipt set(BigInteger _problemId, String _content, BigInteger _create, BigInteger _update, BigInteger _status) {
        final Function function = new Function(
                FUNC_SET, 
                Arrays.<Type>asList(new Uint256(_problemId),
                new Utf8String(_content),
                new Uint256(_create),
                new Uint256(_update),
                new Uint256(_status)),
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public void set(BigInteger _problemId, String _content, BigInteger _create, BigInteger _update, BigInteger _status, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_SET, 
                Arrays.<Type>asList(new Uint256(_problemId),
                new Utf8String(_content),
                new Uint256(_create),
                new Uint256(_update),
                new Uint256(_status)),
                Collections.<TypeReference<?>>emptyList());
        asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForSet(BigInteger _problemId, String _content, BigInteger _create, BigInteger _update, BigInteger _status) {
        final Function function = new Function(
                FUNC_SET, 
                Arrays.<Type>asList(new Uint256(_problemId),
                new Utf8String(_content),
                new Uint256(_create),
                new Uint256(_update),
                new Uint256(_status)),
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple5<BigInteger, String, BigInteger, BigInteger, BigInteger> getSetInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_SET, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}, new TypeReference<Utf8String>() {}, new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}, new TypeReference<Uint256>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple5<BigInteger, String, BigInteger, BigInteger, BigInteger>(

                (BigInteger) results.get(0).getValue(), 
                (String) results.get(1).getValue(), 
                (BigInteger) results.get(2).getValue(), 
                (BigInteger) results.get(3).getValue(), 
                (BigInteger) results.get(4).getValue()
                );
    }

    public BigInteger status() throws ContractException {
        final Function function = new Function(FUNC_STATUS, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public BigInteger update() throws ContractException {
        final Function function = new Function(FUNC_UPDATE, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
        return executeCallWithSingleValueReturn(function, BigInteger.class);
    }

    public static Answer load(String contractAddress, Client client, CryptoKeyPair credential) {
        return new Answer(contractAddress, client, credential);
    }

    public static Answer deploy(Client client, CryptoKeyPair credential) throws ContractException {
        return deploy(Answer.class, client, credential, getBinary(client.getCryptoSuite()), "");
    }
}
